package com.example.keshe;

import com.example.keshe.Dao.impl.ClothingDaoImpl;
import com.example.keshe.util.DruidUtil;
import javafx.fxml.FXML;
import javafx.event.ActionEvent;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javafx.geometry.Insets;
import javafx.scene.layout.GridPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.scene.Scene;

/**
 * 服装信息管理视图的控制器类，包括TableView、Pagination和各种服装相关操作。
 */
public class ClothingView {
    // 分页组件
    @FXML
    private Pagination pageTable; // 分页组件
    private int itemsPerPage = 20; // 每页显示的数据条数

    // 使用FXML注解将FXML文件中的TableView控件与Java代码中的clothingTable字段进行关联
    @FXML
    private TableView<Clothing> clothingTable;

    // 定义与TableView中的列对应的TableColumn字段，并使用FXML注解进行关联
    @FXML
    private TableColumn<Clothing, String> clothingId;
    @FXML
    private TableColumn<Clothing, String> name;
    @FXML
    private TableColumn<Clothing, String> brand;
    @FXML
    private TableColumn<Clothing, String> size;
    @FXML
    private TableColumn<Clothing, String> price;
    @FXML
    private TableColumn<Clothing, String> quantity;
    @FXML
    public TableColumn<Clothing, String> color;
    @FXML
    public TableColumn<Clothing, String> season;
    @FXML
    public TableColumn<Clothing, String> category;

    // 新增输入框
    public TextField inputClothingId;
    public TextField inputClothingName;
    public TextField inputClothingBrand;
    public TextField inputClothingSize;
    public TextField inputClothingPrice;
    public TextField inputClothingQuantity;
    public TextField inputClothingColor;
    public TextField inputClothingSeason;
    public TextField inputClothingCategory;

    // 新增标签
    public Label resultCountLabel;

    // 新增按钮
    public Button addButton;
    public Button queryButton;
    public Button clearButton;
    public Button importButton;
    public Button exportButton;
    public Button closeButton;

    /**
     * 初始化控制器，在加载FXML文件后调用。设置Pagination，加载初始页数据，并配置TableView选择模式。
     */
    @FXML
    private void initialize() {// 页面初始化
        initPagination();// 初始化分页控件
        loadPageData(0);// 加载服装数据，默认加载第一页
        clothingTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);// 设置TableView的多选模式
    }

    /**
     * 初始化Pagination组件，设置总页数，并添加页码变化监听器。
     */
    private void initPagination() {
        pageTable.setPageCount(calculatePageCount());// 设置分页控件的页数
        // 监听页码变化事件，当页码变化时刷新表格数据
        pageTable.currentPageIndexProperty().addListener((observable, oldValue, newValue) -> {
            loadPageData(newValue.intValue());// 根据新的页码加载数据
        });
    }

    /**
     * 根据总记录数和每页显示的条数计算总页数。
     *
     * @return 计算得到的总页数
     */
    private int calculatePageCount() {
        try {
            // 假设你有一个 ClothingDaoImpl 来处理数据库操作
            try (Connection connection = DruidUtil.getConnection()) {
                ClothingDaoImpl clothingDao = new ClothingDaoImpl(connection);
                return (int) Math.ceil((double) clothingDao.getTotalRecords() / itemsPerPage);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 加载指定页码的数据到TableView中。
     *
     * @param pageIndex 要加载的页码
     */
    private void loadPageData(int pageIndex) {
        try {
            try (Connection connection = DruidUtil.getConnection()) {
                ClothingDaoImpl clothingDao = new ClothingDaoImpl(connection);
                List<Clothing> pageData = clothingDao.selectByPage(pageIndex + 1, itemsPerPage);// 获取每页数据
                updateTableView(pageData);  // 将数据加载到 TableView 中
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 更新TableView中的数据。
     *
     * @param clothingList 要更新的服装数据列表
     */
    private void updateTableView(List<Clothing> clothingList) {
        clothingTable.getItems().setAll(clothingList);// 传入List集合，更新TableView
        // 为每列设置单元格值工厂，以从学生对象中获取属性值显示。
        clothingId.setCellValueFactory(new PropertyValueFactory<>("clothingId"));
        name.setCellValueFactory(new PropertyValueFactory<>("name"));
        brand.setCellValueFactory(new PropertyValueFactory<>("brand"));
        size.setCellValueFactory(new PropertyValueFactory<>("size"));
        price.setCellValueFactory(new PropertyValueFactory<>("price"));
        quantity.setCellValueFactory(new PropertyValueFactory<>("quantity"));
        color.setCellValueFactory(new PropertyValueFactory<>("color"));
        season.setCellValueFactory(new PropertyValueFactory<>("season"));
        category.setCellValueFactory(new PropertyValueFactory<>("category"));
    }

    /**
     * 删除选定的服装信息的方法。
     *
     * @param actionEvent 事件对象
     */
    @FXML
    private void btnDel(ActionEvent actionEvent) {
        List<Clothing> selectedClothing = new ArrayList<>(clothingTable.getSelectionModel().getSelectedItems()); // 获取用户在表格中选中的服装信息
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);// 创建一个确认对话框，确保用户希望删除选中的服装信息
        alert.setHeaderText("您确定要删除选定的服装信息吗？(注：有关该服装的销售记录和进货记录也会被删除)");
        Optional<ButtonType> result = alert.showAndWait();
        // 如果用户点击了确认按钮
        if (result.get() == ButtonType.OK) {
            try {
                deleteSelectedClothing(selectedClothing);// 调用方法删除选中的服装信息
                refreshTableView();// 刷新表格，更新显示
            } catch (Exception e) {
                throw new RuntimeException(e); // 数据库操作异常
            }
        }
    }

    /**
     * 刷新TableView显示的方法。
     */
    private void deleteSelectedClothing(List<Clothing> selectedClothing) throws Exception {
        try (Connection connection = DruidUtil.getConnection()) {
            ClothingDaoImpl clothingDao = new ClothingDaoImpl(connection); // 创建 ClothingDaoImpl 对象，用于执行数据库操作
            // 遍历选定的服装信息列表，逐个根据服装 ID 删除对应的记录
            for (Clothing clothing : selectedClothing) {
                clothingDao.deleteByPrimaryKey(clothing.getClothingId());
            }
        }
    }

    /**
     * 刷新 TableView。当删除服装或编辑服装信息后，调用此方法刷新显示。
     */
    private void refreshTableView() {
        int currentPageIndex = pageTable.getCurrentPageIndex();// 获取当前页索引
        int newTotalPages = calculatePageCount();// 计算新的总页数
        pageTable.setPageCount(newTotalPages);// 设置 Pagination 的总页数
        loadPageData(currentPageIndex); // 加载当前页的数据
        // 如果当前页没有数据且不是第一页，加载前一页的数据，并将 Pagination 设置为前一页
        if (clothingTable.getItems().isEmpty() && currentPageIndex > 0) {
            loadPageData(currentPageIndex - 1);
            pageTable.setCurrentPageIndex(currentPageIndex - 1);
        }
    }

    /**
     * 编辑服装的方法。通过创建编辑对话框，允许用户修改选中服装的信息。
     *
     * @param actionEvent 事件对象
     */
    @FXML
    private void btnEdit(ActionEvent actionEvent) {
        Clothing selectedClothing = clothingTable.getSelectionModel().getSelectedItem(); // 获取选定的单个行数据
        if (selectedClothing != null) {
            // 创建编辑对话框，将选中服装的信息传递给对话框
            Dialog<Clothing> dialog = createEditClothingDialog(selectedClothing);
            Optional<Clothing> result = dialog.showAndWait();
            // 处理编辑结果
            result.ifPresent(updatedClothing -> {
                try (Connection connection = DruidUtil.getConnection()) {
                    ClothingDaoImpl clothingDao = new ClothingDaoImpl(connection);
                    clothingDao.updateByPrimaryKey(updatedClothing);
                    refreshTableView();// 刷新数据表格
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }

    /**
     * 创建编辑服装信息的对话框。对话框包括服装号、名称、品牌、大小、价格、颜色、季节、类别字段，但服装号和数量字段不可编辑。
     *
     * @param clothing 选中的服装对象
     * @return 创建的编辑对话框
     */
    private Dialog<Clothing> createEditClothingDialog(Clothing clothing) {
        // 创建对话框
        Dialog<Clothing> dialog = new Dialog<>();
        dialog.setTitle("编辑服装信息");
        dialog.setHeaderText("注:服装号和数量不可编辑");
        // 设置按钮
        ButtonType saveButtonType = new ButtonType("保存", ButtonBar.ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(saveButtonType, ButtonType.CANCEL);
        // 设置布局
        GridPane editGrid = new GridPane();
        editGrid.setHgap(10);
        editGrid.setVgap(10);
        editGrid.setPadding(new Insets(20, 150, 10, 10));
        // 在网格面板中添加编辑输入框
        TextField clothingIdField = new TextField(clothing.getClothingId());
        clothingIdField.setEditable(false);  // 设置为不可编辑
        TextField nameField = new TextField(clothing.getName());
        TextField brandField = new TextField(clothing.getBrand());
        TextField sizeField = new TextField(clothing.getSize());
        TextField priceField = new TextField(clothing.getPrice());
        TextField colorField = new TextField(clothing.getColor());
        TextField seasonField = new TextField(clothing.getSeason());
        TextField categoryField = new TextField(clothing.getCategory());
        // 设置数量字段为不可编辑
        TextField quantityField = new TextField(clothing.getQuantity());
        quantityField.setEditable(false);
        editGrid.add(new Label("服装号:"), 0, 0);
        editGrid.add(clothingIdField, 1, 0);
        editGrid.add(new Label("名称:"), 0, 1);
        editGrid.add(nameField, 1, 1);
        editGrid.add(new Label("品牌:"), 0, 2);
        editGrid.add(brandField, 1, 2);
        editGrid.add(new Label("大小:"), 0, 3);
        editGrid.add(sizeField, 1, 3);
        editGrid.add(new Label("价格:"), 0, 4);
        editGrid.add(priceField, 1, 4);
        editGrid.add(new Label("数量:"), 0, 5);
        editGrid.add(quantityField, 1, 5);
        editGrid.add(new Label("颜色:"), 0, 6);
        editGrid.add(colorField, 1, 6);
        editGrid.add(new Label("季节:"), 0, 7);
        editGrid.add(seasonField, 1, 7);
        editGrid.add(new Label("类别:"), 0, 8);
        editGrid.add(categoryField, 1, 8);
        dialog.getDialogPane().setContent(editGrid);
        // 设置对话框的结果转换器
        dialog.setResultConverter(dialogButton -> {
            if (dialogButton == saveButtonType) {
                // 如果点击保存按钮，将编辑后的服装信息返回
                return new Clothing(
                        clothingIdField.getText(),
                        nameField.getText(),
                        brandField.getText(),
                        sizeField.getText(),
                        priceField.getText(),
                        quantityField.getText(),
                        colorField.getText(),
                        seasonField.getText(),
                        categoryField.getText()
                );
            }
            return null; // 点击取消按钮或关闭对话框，返回null
        });
        return dialog;
    }

    /**
     * 添加新服装的方法。通过获取输入框的值，验证输入有效性，并将新服装信息插入数据库。
     *
     * @param actionEvent 事件对象
     */
    @FXML
    private void addClothing(ActionEvent actionEvent) {
        // 获取输入框的值
        String clothingId = inputClothingId.getText();
        String clothingName = inputClothingName.getText();
        String clothingBrand = inputClothingBrand.getText();
        String clothingSize = inputClothingSize.getText();
        String clothingPrice = inputClothingPrice.getText();
        String clothingQuantity = inputClothingQuantity.getText();
        String clothingColor = inputClothingColor.getText();
        String clothingSeason = inputClothingSeason.getText();
        String clothingCategory = inputClothingCategory.getText();
        // 验证输入是否有效
        if (validateClothingInput(clothingId, clothingName, clothingBrand, clothingSize, clothingPrice,clothingColor,clothingSeason,clothingCategory)) {
            try (Connection connection = DruidUtil.getConnection()) {
                ClothingDaoImpl clothingDao = new ClothingDaoImpl(connection);// 创建服装数据访问对象
                // 检查是否已经存在相同的服装号
                if (!clothingDao.isDuplicateClothingId(clothingId)) {
                    // 检查是否已经存在相同名称、品牌、大小和价格的服装
                    if (!clothingDao.isDuplicateClothing(clothingId, clothingName, clothingBrand, clothingSize,clothingColor,clothingSeason,clothingCategory)) {
                        // 服装号和信息都不重复，创建新的服装对象
                        Clothing newClothing = new Clothing(
                                clothingId,
                                clothingName,
                                clothingBrand,
                                clothingSize,
                                clothingPrice,
                                clothingQuantity.isEmpty() ? "0" : clothingQuantity,
                                clothingColor,
                                clothingSeason,
                                clothingCategory
                        );
                        clothingDao.insert(newClothing); // 插入新服装信息
                        refreshTableView();// 刷新数据表格
                    } else {
                        // 有相同的服装信息，弹出警告框
                        Alert alert = new Alert(Alert.AlertType.WARNING);
                        alert.setHeaderText("服装信息重复");
                        alert.setContentText("已经存在相同名称、品牌和大小的服装!");
                        alert.showAndWait();
                    }
                } else {
                    // 有相同的服装号，弹出警告框
                    Alert alert = new Alert(Alert.AlertType.WARNING);
                    alert.setHeaderText("服装号重复");
                    alert.setContentText("已经存在相同的服装号!");
                    alert.showAndWait();
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else {
            // 弹出警告框，输入无效
            Alert alert = new Alert(Alert.AlertType.WARNING);
            alert.setHeaderText("输入无效");
            alert.setContentText("服装号、名称、品牌、大小、价格、颜色、季节和类别为必填项!");
            alert.showAndWait();
        }
    }

    /**
     * 验证输入是否有效。用于在添加新服装前检查服装号、名称、品牌、大小、价格、颜色、季节和类别字段是否都已填写。
     *
     * @param id      服装号
     * @param name    名称
     * @param brand   品牌
     * @param size    大小
     * @param price   价格
     * @param color   颜色
     * @param season  季节
     * @param category 类别
     * @return 如果输入有效，返回 true；否则，返回 false。
     */
    private boolean validateClothingInput(String id, String name, String brand, String size, String price, String color, String season, String category) {
        return !id.isEmpty() && !name.isEmpty() && !brand.isEmpty() && !size.isEmpty() && !price.isEmpty()
                && !color.isEmpty() && !season.isEmpty() && !category.isEmpty();
    }

    /**
     * 查询服装的方法。根据输入的条件查询服装信息，更新表格数据和显示的查询结果数量。
     *
     * @param actionEvent 事件对象
     */
    @FXML
    private void queryClothing(ActionEvent actionEvent) {
        // 获取查询条件的值
        String clothingId = inputClothingId.getText();
        String clothingName = inputClothingName.getText();
        String clothingBrand = inputClothingBrand.getText();
        String clothingSize = inputClothingSize.getText();
        String clothingPrice = inputClothingPrice.getText();
        String clothingQuantity = inputClothingQuantity.getText();
        String clothingColor = inputClothingColor.getText();
        String clothingCategory = inputClothingCategory.getText();
        String clothingSeason = inputClothingSeason.getText();
        try (Connection connection = DruidUtil.getConnection()) {
            ClothingDaoImpl clothingDao = new ClothingDaoImpl(connection);// 创建服装数据访问对象
            List<Clothing> clothingList = clothingDao.queryClothing(
                    clothingId, clothingName, clothingBrand, clothingSize,
                    clothingPrice, clothingQuantity, clothingColor,
                    clothingSeason,clothingCategory
            ); // 执行查询
            updateTableView(clothingList);// 更新表格数据
            resultCountLabel.setText("共查询到 " + clothingList.size() + " 条记录。");// 更新查询结果数量
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 刷新数据的方法。重新计算总页数，加载当前页的数据，并根据需要加载前一页的数据。
     */
    public void refreshData() {
        int currentPageIndex = pageTable.getCurrentPageIndex();// 获取当前页索引
        try (Connection connection = DruidUtil.getConnection()) {
            ClothingDaoImpl clothingDao = new ClothingDaoImpl(connection);// 创建服装数据访问对象
            int newTotalPages = calculatePageCount(); // 计算新的总页数
            pageTable.setPageCount(newTotalPages); // 设置 Pagination 的总页数
            loadPageData(currentPageIndex);// 加载当前页的数据
            // 如果当前页没有数据且不是第一页，加载前一页的数据，并将 Pagination 设置为前一页
            if (clothingTable.getItems().isEmpty() && currentPageIndex > 0) {
                loadPageData(currentPageIndex - 1);
                pageTable.setCurrentPageIndex(currentPageIndex - 1);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 清空所有输入字段的内容，然后调用刷新方法。用于在点击清空按钮时，清空输入框，并刷新表格数据。
     *
     * @param actionEvent 事件对象
     */
    public void clearFields(ActionEvent actionEvent) {
        inputClothingId.clear();
        inputClothingName.clear();
        inputClothingBrand.clear();
        inputClothingSize.clear();
        inputClothingPrice.clear();
        inputClothingQuantity.clear();
        inputClothingColor.clear();
        inputClothingSeason.clear();
        inputClothingCategory.clear();
        resultCountLabel.setText("");// 清空查询结果数量标签
        refreshData(); // 调用刷新方法
    }

    /**
     * 导入数据的方法。通过选择 Excel 文件，导入数据并刷新表格数据。
     *
     * @param actionEvent 事件对象
     */
    @FXML
    public void importData(ActionEvent actionEvent) {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("选择导入文件");
        fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Excel文件", "*.xlsx"));
        File selectedFile = fileChooser.showOpenDialog(new Stage());
        if (selectedFile != null) {
            ExcelClothing.importFromExcel(selectedFile);// 这里可以根据实际需求添加导入的逻辑
            refreshData();// 导入完成后刷新表格数据
        }
    }

    /**
     * 导出数据的方法。将所有服装数据导出到 Excel 文件，并由用户选择导出路径。
     *
     * @param actionEvent 事件对象
     */
    @FXML
    public void exportData(ActionEvent actionEvent) {
        try (Connection connection = DruidUtil.getConnection()) {
            ClothingDaoImpl clothingDao = new ClothingDaoImpl(connection);// 创建服装数据访问对象
            List<Clothing> allClothing = clothingDao.selectAll(); // 获取所有服装数据
            // 获取用户选择的导出文件路径
            FileChooser fileChooser = new FileChooser();
            fileChooser.setTitle("选择导出路径");
            fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Excel 文件", "*.xlsx"));
            File selectedFile = fileChooser.showSaveDialog(null);
            if (selectedFile != null) {
                ExcelClothing.exportToExcel(allClothing, selectedFile);// 调用 exportToExcel 导出所有数据
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭应用的方法。用于在点击关闭按钮时，关闭应用程序。
     *
     * @param actionEvent 事件对象
     */
    public void closeApp(ActionEvent actionEvent) {
        Scene scene = ((Node) actionEvent.getSource()).getScene(); // 获取当前控件所在的 Scene
        // 获取当前窗口并关闭
        Stage stage = (Stage) scene.getWindow();
        stage.hide();
    }
}
